package vue2D;


import java.util.*;

import android.content.Context;
import android.graphics.*;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


import personnage.Personnage;
import personnage.PersonnageDefaut;


import labyrinthe.ExceptionCollision;
import labyrinthe.ExceptionSortie;
import labyrinthe.Salle;
import labyrinthe.grille.*;


/**
* Classe Dessin
*
* Permet de dessiner le jeu dans la fenêtre.
* 
* @author IUT, Clement IBANEZ, Guillaume MARQUES
* @version 21-10-2012
*/

public class Dessin  extends SurfaceView implements SurfaceHolder.Callback 
{

    public static final int unite = 10;
    private Paint p; //pinceau
    protected LabyrintheGrille labyrinthe;
    protected Personnage pacman;
    protected ArrayList<PersonnageDefaut> monstres;

    Case entree;
    Case sortie;
    
    SurfaceHolder mSurfaceHolder;
    DrawingThread mThread;

    /**
    * Constructeur<br />
    *
    * 
    * @param labyrinthe
    *               le LabyrintheGrille sur lequel on va jouer et 
    * @param bob 
    *               le personnage avec lequel on va joueur
    */   
    public Dessin(LabyrintheGrille labyrinthe,PersonnageDefaut pacman,ArrayList<PersonnageDefaut> monstres, Context c)
    {
    	super(c);
    	
        this.labyrinthe=labyrinthe;
        this.monstres=monstres;
        this.pacman=pacman;
        this.p = new Paint();
        p.setStyle(Paint.Style.FILL);
        
        entree= (Case) labyrinthe.getEntree();
        sortie= (Case) labyrinthe.getSortie();
        
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
        mThread = new DrawingThread();
        
        //setPreferredSize(new Dimension(labyrinthe.getLargeur()*unite, labyrinthe.getHauteur()*unite));
        // on ajoute un ecouteur sur le clavier attache au dessin du labyrinthe                             
        //addKeyListener((KeyListener) pacman);                              
    }
    
    
    /**
     * Méthode publique majCoordonneesPersonnage<br />
     * 
     * Permet de mettre à jour les coordonnées sur le jeu d'un personnage.
     * 
     * @param monPersonnage
     */
    public void majCoordonneesPersonnage(PersonnageDefaut monPersonnage)
    {
    
    	Salle s= monPersonnage.getPosition();
    	
    	if (s==null) 
    		return;
    	
    	int xpixCible = ((SalleCarree) s).getColonne()*unite;
    	int ypixCible = ((SalleCarree) s).getLigne()*unite;
   
    	if(s==entree)
    	{
    		monPersonnage.xpix=xpixCible;
    		monPersonnage.ypix=ypixCible;
    	}
    	
    	if (monPersonnage.xpix<xpixCible) monPersonnage.xpix++;
	    if (monPersonnage.xpix>xpixCible) monPersonnage.xpix--;
	    if (monPersonnage.ypix<ypixCible) monPersonnage.ypix++; 
	    if (monPersonnage.ypix>ypixCible) monPersonnage.ypix--;
   
    	monPersonnage.setDeplacementPossible(((monPersonnage.xpix==xpixCible)&&(monPersonnage.ypix==ypixCible)));
    }
    	
  
    

    /**
    * Méthode publique dessinFond.<br />
    *
    * Dessine le fond du jeu. Il s'agit d'un fond noir.
    *
    * @param g 
    *       Objet Graphics sur lequel on va dessiner
    */   
    public void dessinFond(Canvas c)
    {
       c.drawRGB(0, 0, 0); //On colorie tout le fond en noir
    }
    

    /**
    * Méthode publique dessinSalles.<br />
    *
    * Dessine les salles.
    *
    * @param g 
    *           Objet Graphics sur lequel on va dessiner
    */   
    public void dessinSalles(Canvas c)
    {
        // On récupère toutes les salles
        Collection<Salle> salles=labyrinthe.getSalles();

        
        p.setColor(Color.rgb(255, 255, 255));
        
        //Puis on les dessine
        for (Salle s: salles)
        {
            int i = ((Case) s).getLigne();
            int j = ((Case) s).getColonne();
       
            c.drawRect(j*unite,i*unite,j*unite+unite,i*unite+unite, p);
        }
    }  

    
    public void dessinEntreeSortie(Canvas c)
    {
    	
        //On dessine la salle d'entrée
    	p.setColor(Color.rgb(255, 0, 0));
        c.drawRect(entree.getColonne()*unite, entree.getLigne()*unite, (entree.getColonne()+1)*unite,(entree.getLigne()+1)*unite,p);

        //On dessine la salle de sortie
        p.setColor(Color.rgb(0, 0, 255));
        c.drawRect(sortie.getColonne()*unite, sortie.getLigne()*unite, (sortie.getColonne()+1)*unite,(sortie.getLigne()+1)*unite,p);
    }
    /**    
     * Méthode publique dessinHeros.<br />
     *
     * Dessine le hero
     *
     * @param g 
     *           Objet Graphics sur lequel on va dessiner
     */   
    public void dessinPacman(Canvas c)
     {
         p.setColor(Color.rgb(125,40,255));
         
         majCoordonneesPersonnage((PersonnageDefaut) pacman);
         pacman.paint(c, ((PersonnageDefaut) pacman).xpix,((PersonnageDefaut) pacman).ypix);
     }
   
    public void dessinMonstres(Canvas c)
    {
        for (PersonnageDefaut m : monstres)
        {
            majCoordonneesPersonnage(m);
            m.paint(c, m.xpix, m.ypix);
        }
    }

     
    /**
    * Méthode publique paintComponent.<br />
    *
    * Execute toutes les méthodes dessinXxx() pour dessiner le labyrinthe.
    *
    * @param g 
    *           Objet Graphics sur lequel on va dessiner
    */   
    public void onDraw(Canvas c)
    {	
			
        //On dessine le jeu avec toutes les méthodes précédentes.
        dessinFond(c);
        
        dessinSalles(c);
        dessinEntreeSortie(c);
        dessinPacman(c);
        dessinMonstres(c);
    }


	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		 mThread.keepRunning = true;
		 mThread.start();
		
	}


	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		 mThread.keepRunning = false;
		    boolean retry = true;
		    while (retry) {
		      try {
		        mThread.join();
		        retry = false;
		      } catch (InterruptedException e) {}
		    }
		
	}
		
	private class DrawingThread extends Thread
	{
	    boolean keepRunning = true;
	
	    @Override
	    public void run()
	    {
	
	    	
	      Canvas canvas;
	      while (keepRunning)
	      {
	    	  
	    	  for(Personnage monstre: monstres)
			  {
					if(((PersonnageDefaut) monstre).getDeplacementPossible())
					{
						Collection<Salle> sallesAccessibles1 = labyrinthe.sallesAccessibles(monstre);
				
						Salle destination = monstre.faitSonChoix(sallesAccessibles1);
						try {
							destination.recevoir(monstre, pacman);
						} catch (ExceptionSortie e) {
							
						} catch (ExceptionCollision e) {
							
							labyrinthe.entrer(pacman);
						}
					}
				}
	    	  
	    	  //Log.w("test", "test");
	        canvas = null;
	
	        try {
	          canvas = mSurfaceHolder.lockCanvas();
	          synchronized (mSurfaceHolder) {
	            onDraw(canvas);
	          }
	          
	        } finally {
	          if (canvas != null)
	            mSurfaceHolder.unlockCanvasAndPost(canvas);
	        }
	
	        // Pour dessiner à 30 fps
	        try {
	          Thread.sleep(30);
	        } catch (InterruptedException e) {}
	      }
	    }
	  }
}
